feat: opt-in channel-scoped PostgreSQL temp table state store - #1994
Draft
filipecabaco wants to merge 2 commits into
Draft
feat: opt-in channel-scoped PostgreSQL temp table state store#1994filipecabaco wants to merge 2 commits into
filipecabaco wants to merge 2 commits into
Conversation
Add a per-channel key/value store backed by a PostgreSQL TEMP TABLE, opted into via `config.state.enabled` on private channels. Each channel gets a dedicated session/temp table exposed over a new "state" message (put/insert/update/delete/get/clear) with optimistic versioning. Bounded by input limits and a per-tenant cap; best-effort so it never blocks the join.
Contributor
CRAP Score Report |
…ssues Applies the confirmed findings from the review of the temp state store: - Multi-node correctness: the capacity check no longer queries the tenant's shared pooled connection (which can live on another node, where DBConnection checkout cannot work). start/3 drops the db_conn argument entirely. - Capacity enforcement in two layers: an exact node-local gate via Realtime.Registry inside init (store starts are serialized through the DynamicSupervisor), plus a cluster-wide backstop where the store counts pg_stat_activity sessions from its own connection after connecting and stops itself when over the limit. Removes the check-then-act race on the shared pool and the overclaiming "authoritative" moduledoc. - Non-blocking starts: init is IO-free; the database connection, session setup and capacity backstop run in handle_continue, so a slow tenant database can no longer stall the shared supervisor or block channel joins node-wide. - Lifecycle: the store monitors the tenant's Connect process and stops when it goes down, so rebalancing and db-settings changes no longer leave dedicated sessions behind. Sessions opened on failure paths are closed via terminate. - Connection budgeting: check_tenant_connection reserves the temp state store capacity (capacity_limit(max_connections)) on top of pooled requirements so these sessions can't silently eat the headroom Connect needs to re-provision. - Encoding: values are bound as JSON text and cast server-side (::text::jsonb), fixing the double-JSON-encoding that stored every value as a jsonb scalar string and under-counted the size limit; the compensating decode/1 is gone. - Limits: the per-write count(*) scan is replaced by an exact app-side key count (the owner process serializes all mutations); at the cap, puts to existing keys go through an update-only path. - Timeouts: queries run with an explicit 15s timeout and GenServer.call uses 20s, so slow writes report their real outcome instead of :unavailable for a write that actually committed. Idle sessions ping at 30s instead of 1s and the connection keeps the tenant's queue_target. - Input validation: keys must be strings (non-binary keys previously crashed the store), JSON null for state.enabled/private/expected no longer raises or is rejected, and the no-store "state" fallback is rate-counted. - The channel clears the store assign when the store dies. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lg7KHUrgo3zf7omHkoNQEX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What kind of change does this PR introduce?
Add a per-channel key/value store backed by a PostgreSQL TEMP TABLE, opted into via
config.state.enabledon private channels. Each channel gets a dedicated session/temp table exposed over a new "state" message (put/insert/update/delete/get/clear) with optimistic versioning. Bounded by input limits and a per-tenant cap; best-effort so it never blocks the join.